﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Collections.ObjectModel;
using Microsoft.TeamFoundation.Client;
using Microsoft.TeamFoundation.Common;
using Microsoft.TeamFoundation.Framework.Client;
using Microsoft.TeamFoundation.Framework.Common;
using Microsoft.TeamFoundation.WorkItemTracking.Client;
using Microsoft.TeamFoundation.Server;

using Microsoft.TeamFoundation;
using System.Xml;

namespace GetAreas
{
    class Program
    {
        static private TfsTeamProjectCollection tpc;
        static private IIdentityManagementService ims;
        static private SecurityNamespace namesp;
        
        static void Main(string[] args)
        {     
            
            try
            {
                if (args.Length == 0)
                {
                    Console.WriteLine("Please provide the Team Project Collection Uri.");
                    Environment.Exit(0);
                }
                tpc = new TfsTeamProjectCollection(new Uri(args[0]));
                
                ICommonStructureService css = tpc.GetService<ICommonStructureService>();
                ISecurityService secSvc = tpc.GetService<ISecurityService>();
                ims = tpc.GetService<IIdentityManagementService>();

                namesp = secSvc.GetSecurityNamespace(AuthorizationSecurityConstants.CommonStructureNodeSecurityGuid);

                

                tpc.EnsureAuthenticated();

                if (tpc.HasAuthenticated == true)
                {
                    ProjectInfo[] teamProjects = css.ListAllProjects();
                    XmlElement element = null;

                    Console.WriteLine();
                    Console.WriteLine(new string('=', 40));
                    Console.WriteLine();

                    foreach (ProjectInfo teamProject in teamProjects)
                    {
                        foreach (NodeInfo node in css.ListStructures(teamProject.Uri))
                        {
                            if (node.StructureType != "ProjectModelHierarchy")
                            {
                                continue;
                            }
                
                            element = css.GetNodesXml(new string[] { node.Uri }, true);

                            ListChildNodes(node.Name, element.ChildNodes[0]);

                        }

                    }            

                }                
                
            }
            catch (Exception e)
            {

                Console.WriteLine(e.Message);
                Console.WriteLine(e.InnerException);
            }
            
        }

        static private void ListChildNodes(string parentPath, XmlNode parentNode)
        {
            
            Console.WriteLine("<<<Area Details>>> ");
            for (int i = 0; i <= parentNode.Attributes.Count - 1;i++ )
            {
              
                Console.WriteLine("{0} {1}",parentNode.Attributes[i].Name, parentNode.Attributes[i].Value);                
            }
            AccessControlList acl = namesp.QueryAccessControlList(parentNode.Attributes["NodeID"].Value, null, true);
            Console.WriteLine();
            Console.WriteLine("<<<Users>>> ");

            foreach (Microsoft.TeamFoundation.Framework.Client.AccessControlEntry ace in acl.AccessControlEntries)
            {
                
                TeamFoundationIdentity id = ims.ReadIdentity(ace.Descriptor, MembershipQuery.Direct, ReadIdentityOptions.None);
                
                if (id.IsContainer)
                {                    
                    EnumGroups(id, 0);
                    continue;
                }

                Console.WriteLine(id.DisplayName);                
            }

            Console.WriteLine();
            Console.WriteLine(new string('=', 40));
            Console.WriteLine();

            if (parentNode.ChildNodes[0] == null)
            {
                return;
            }
            foreach (XmlNode node in parentNode.ChildNodes[0].ChildNodes)
            {
                string nodePath = node.Attributes["Path"].Value;                
                ListChildNodes(nodePath, node);
            }

            
        }

        static private int EnumGroups(TeamFoundationIdentity id, int count)
        {
            Console.WriteLine(new String('-', 2 * count) + id.DisplayName + " [G] TfsID:" +id.TeamFoundationId.ToString() );
            for (int i = 0; i < id.Members.Length; i++)
            {
                TeamFoundationIdentity newId = ims.ReadIdentity(id.Members[i], MembershipQuery.Direct, ReadIdentityOptions.None);

                if (newId.IsContainer)
                {
                    count++;
                    EnumGroups(newId, count);
                    count--;
                    continue;
                    
                }
                Console.WriteLine(new String('-', 2 * (count+1))  + newId.DisplayName  + " " +id.TeamFoundationId.ToString() );
            }

            return count;
        }

        
    }
}

